﻿#light

// "Julien", http://cs.hubfs.net/forums/thread/7472.aspx

namespace Common.Monads

type State<'state,'a> = State of ('state -> 'a * 'state)

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]   
module State = begin
  type StateBuilder =
    class
      new : unit -> StateBuilder
      member Bind : m:State<'state,'a> * f:('a -> State<'state,'b>) -> State<'state,'b>
      member BindUsing : m:State<'state,'a> * f:('a -> State<'state,'b>) ->State<'state,'b> when 'a :> System.IDisposable
      member Combine : m1:State<'state,unit> * m2:State<'state,'a> -> State<'state,'a>
      member Delay : f:(unit -> State<'state,'a>) -> State<'state,'a>
      member For : s:#seq<'a> * f:('a -> State<unit,'b>) -> State<unit,unit>
      //member Let : x:'a * f:('a -> 'b) -> 'b
      member Return : x:'a -> State<'state,'a>
      member TryFinally : m:State<'state,'a1> * f:(unit -> unit) -> State<'state,'a1>
      member TryWith : m:State<'state,'a> * f:(exn -> State<'state,'a>) -> State<'state,'a>
      member Using : x:'a * f:('a -> State<'state,'b>) -> State<'state,'b> when 'a :> System.IDisposable
      member While : p:(unit -> bool) * m:State<unit,'a> -> State<unit,unit>
      member Zero : unit -> State<'state,unit>
    end

  ///[state {...}] is the [State] continuation builder.
  val state : StateBuilder
 
  ///[Run m state] runs [m] with the [state] and returns the value and state.
  val Run : State<'state,'a> -> 'state -> 'a * 'state
 
  ///[GetState] is a continuation returning the current state of the continuation.
  ///Example of use : [state { let! state = get ... }]
  val GetState : State<'state,'state>
 
  ///[SetState newState] is a continuation putting [newState] as the new state of the continuation.
  ///Example of use : [state { do! put newState }] 
  val SetState : 'state -> State<'state,unit>

  ///[MapState f] is a continuation putting [f oldState] as the new state of the continuation.
  ///Example of use : [state { do! modify (fun oldState -> oldState) }]   
  val MapState : ('state -> 'state) -> State<'state,unit>

  ///[Eval m s] returns the state of [m] at the end of the continuation computation
  ///which has used <img src="/emoticons/emotion-56.gif" alt="Sleep [S]" /> as its initial state.   
  val Eval : State<'state,'a> -> 'state -> 'state
 
  ///[Exec m s] returns the value of [m] at the end of the continuation computation
  ///which has used <img src="/emoticons/emotion-56.gif" alt="Sleep [S]" /> as its initial state.
  val Exec : State<'state,'a> -> 'state -> 'a
 
  ///[MapStateAndResult f m] returns a new [State] continuation by applying [f value state] where
  ///[value] and [state] are the value and state of [m].
  val MapStateAndResult : ('a -> 'state -> 'b * 'state) -> State<'state,'a> -> State<'state,'b>
end
